home *** CD-ROM | disk | FTP | other *** search
- /*
- * This software is copyrighted as noted below. It may be freely copied,
- * modified, and redistributed, provided that the copyright notice is
- * preserved on all copies.
- *
- * There is no warranty or other guarantee of fitness for this software,
- * it is provided solely "as is". Bug reports or fixes may be sent
- * to the author, who may or may not act on them as he desires.
- *
- * You may not include this software in a program or other software product
- * without supplying the source, or without informing the end-user that the
- * source is available for no extra charge.
- *
- * If you modify this software, you should include a notice giving the
- * name of the person performing the modification, the date of modification,
- * and the reason for such modification.
- */
- /*
- * RLE File converter/translater
- * John Peterson, Jan-Feb '91
- *
- * Copyright (c) 1991 John Peterson
- *
- * Stuff still to do:
- * - Error recovery needs more work - sort out fatal errors (DONE)
- * - Deal with memory allocation problems as a separate
- * error class, and have "emergancy stash" ready (DONE)
- * - Should do something intelligent with basic color maps (DONE)
- * - Be smarter about tying filenames to windows.
- * - Check the machine/system configuration (DONE)
- * - Windows should stack with offsets (so new ones don't
- * completly bury the old) (DONE)
- * - Activate events should mess with the menus (DONE)
- * - Finder stuff (File types, bundles, icons, etc). (DONE)
- * _ Spencer's radius card.
- * - Jamie Painter sez it croaks on empty PICT files from MacDraw (FIXED)
- * Stuff maybe someday...
- * - Be less of a memory hog (don't hold your breath, this
- * is lotsa work..)
- * - Grow boxes/scroll bars (also lotsa work)
- * - Zoom modes, other GetX11 frobs...
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <QDOffscreen.h>
-
- #include "rle.h"
- #include "macstuff.h"
- #include "macimg.h"
-
- Ptr PanicStash; /* Buffer to bring up an "out of memory" dialog */
-
- rle_hdr inglob; /* Globals for RLE lib */
-
- /*
- * Create a window for displaying an image. RlePict's
- * info is stashed in the WRefCon.
- */
- static void
- CreateWindow( GWorldPtr gw, char * name )
- {
- WindowPtr win;
- ImageWin * imgWin;
-
- win = MakeWindow( gw->portRect.right - gw->portRect.left,
- gw->portRect.bottom - gw->portRect.top, name );
- CopyGWtoWindow( gw, win );
-
- imgWin = (ImageWin *) NewPtr( sizeof( ImageWin ));
- if (!imgWin) MemoryError( "Can't create window - out of memory" );
- imgWin->tag = 0xDEADBEEF;
- imgWin->win = win;
- imgWin->gw = gw;
- imgWin->name = (char *) malloc( strlen( name ) + 1L );
- if (! imgWin->name )
- MemoryError( "Can't allocate window name" );
- strcpy( imgWin->name, name );
- SetWRefCon( win, (long) imgWin );
- }
-
- /*
- * RLE to PICT file
- */
- void
- RLEtoPICT()
- {
- GWorldPtr mygw;
- char namestore[256];
- char * filename = namestore;
- register rle_pixel *rptr, *gptr, *bptr, *aptr, *qdptr;
- register long i, j;
- PixMapPtr ppm;
- long mapSize;
- CTabPtr macCtab = NULL;
- CTabHandle macCtabHandle = NULL;
- rle_pixel **rows;
- Rect r;
- QDErr err;
- WindowPtr win;
- ImageWin * imgWin;
- DialogPtr progressDlog;
- char MMUMode = 1; /* 1 = 32 bit mode */
-
- if ( !OldFilename( "RLE file:", filename, '????' ) )
- return;
- inglob.rle_file = fopen( filename, "rb" );
- CHECK( inglob.rle_file, "Can't open RLE file\n" );
- err = rle_get_setup( &inglob );
-
- /*
- * Report error if it dies...
- */
- if (err != RLE_SUCCESS)
- {
- switch ( err )
- {
- case RLE_NOT_RLE:
- ErrorAlert( "Tried to read a non-RLE file" );
- break;
-
- case RLE_EMPTY:
- ErrorAlert( "RLE file was empty" );
- break;
-
- case RLE_EOF:
- ErrorAlert( "RLE header was incomplete" );
- break;
-
- default:
- ErrorAlert( "Error encountered reading RLE file header" );
- break;
- }
- fclose( inglob.rle_file );
- return;
- }
-
- if ( rle_row_alloc( &inglob, &rows ) )
- MemoryError( "Ran out of memory\n" );
-
- r.left = inglob.xmin;
- r.right = inglob.xmax + 1;
- r.top = inglob.ymin;
- r.bottom = inglob.ymax + 1;
-
- /*
- * Do some sanity checks on the kind of file we're reading
- * (We don't do funky channels or cmaps).
- */
- if (inglob.ncmap)
- if ((inglob.cmaplen != 8)
- && (inglob.ncmap != 3)
- && (inglob.ncmap != 1))
- {
- ErrorAlert( "Sorry - this image's color map not supported" );
- fclose( inglob.rle_file );
- return;
- }
-
- if ((inglob.ncolors != 3) && (inglob.ncolors != 1))
- {
- ErrorAlert( "Sorry - only one and three channel RLE images" );
- fclose( inglob.rle_file );
- return;
- }
-
- /*
- * If given a valid color map, convert it into a QuickDraw
- * color map.
- */
- if (inglob.ncmap)
- {
- mapSize = 1 << inglob.cmaplen;
-
- macCtabHandle = (CTabHandle)
- NewHandle( sizeof( ColorTable ) + sizeof( ColorSpec ) * mapSize );
- if ( !macCtabHandle )
- MemoryError( "No memory for color map" );
-
- HLock( macCtabHandle ); /* I hate handles */
- macCtab = *macCtabHandle;
- macCtab->ctSeed = GetCTSeed();
- macCtab->ctFlags = 0; /* Not a device... */
- macCtab->ctSize = mapSize - 1;
-
- for (i = 0; i < mapSize; i++)
- {
- macCtab->ctTable[i].value = i;
- macCtab->ctTable[i].rgb.red = inglob.cmap[i];
- macCtab->ctTable[i].rgb.green = (inglob.ncmap == 3) ? inglob.cmap[i+mapSize]
- : inglob.cmap[i];
- macCtab->ctTable[i].rgb.blue = (inglob.ncmap == 3) ? inglob.cmap[i+2 * mapSize]
- : inglob.cmap[i];
- }
- HUnlock( macCtabHandle );
- }
- else
- {
- if (inglob.ncolors == 1) /* One chan, no cmap, must be B&W */
- macCtabHandle = GetCTable( 8 + 32 ); /* Built-in grayscale */
- else
- macCtabHandle = NULL; /* No table */
- }
-
- /*
- * Allocate an off-screen image ("GWorld" in MacSpeak) for
- * storing the image. Should check the error return.
- */
- err = NewGWorld( &mygw, (inglob.ncolors == 3) ? 32 : 8, &r, macCtabHandle, NULL, 0 );
- if (err)
- MemoryError( "Error converting RLE file, no memory for off-screen buffer" );
-
- /* CTable was copied into gworld, so get rid of our copy */
- if (macCtabHandle)
- DisposCTable( macCtabHandle );
-
- if (! LockPixels( mygw->portPixMap ))
- MemoryError( "Can't lock memory for image" );
-
- progressDlog = InitProgress( 300 ); /* "Reading RLE" progress */
-
- HLock( mygw->portPixMap );
- ppm = *(mygw->portPixMap);
-
- for (i = inglob.ymax; i >= inglob.ymin; i--)
- {
- rle_getrow( &inglob, rows );
- if (inglob.ncolors == 3)
- {
- rptr = &(rows[0][inglob.xmin]);
- gptr = &(rows[1][inglob.xmin]);
- bptr = &(rows[2][inglob.xmin]);
- }
- else
- rptr = gptr = bptr = &(rows[0][inglob.xmin]);
- aptr = inglob.alpha ? rows[-1] : NULL;
-
- qdptr = (rle_pixel *) &(ppm->baseAddr[(long) (i - inglob.ymin) * (long) (ppm->rowBytes & 0x7FFF) + (long)0]);
- /*
- * Note qdptr may be pointing off to memory out on a 32 bit NuBus card.
- * If so, then the MMU must be swapped into 32 bit mode to access the
- * memory. Leave it to Spencer to turn this up...
- */
- SwapMMUMode( &MMUMode );
-
- if (inglob.ncolors == 1)
- {
- if (inglob.ncmap)
- for (j = inglob.xmin; j <= inglob.xmax; j++)
- *qdptr++ = *rptr++;
- else
- for (j = inglob.xmin; j <= inglob.xmax; j++) /* Convert to screwy Color QD */
- *qdptr++ = 255 - *rptr++;
- }
- else
- /* 32 bit QuickDraw stores pixels in ARGBARGB... format */
- for (j = inglob.xmin; j <= inglob.xmax; j++)
- {
- *qdptr++ = aptr ? *aptr++ : 0xFF;
- *qdptr++ = *rptr++;
- *qdptr++ = *gptr++;
- *qdptr++ = *bptr++;
- }
-
- SwapMMUMode( &MMUMode );
-
- if (i && (!(i % 10)))
- UpdateProgress( progressDlog,
- 1.0 - ((double) (i - inglob.ymin))
- / (double) (inglob.ymax - inglob.ymin));
- }
- HUnlock( mygw->portPixMap );
- fclose( inglob.rle_file );
- UpdateProgress( progressDlog, 1.0 );
- UnlockPixels( mygw->portPixMap );
- CreateWindow( mygw, filename );
- DoneProgress( progressDlog );
- }
-
- /*
- * Save a GWorld as an RLE file. The GWorld is assumed to be 32 bits
- * deep.
- */
- void
- PICTtoRLE(GWorldPtr mygw, char * defname)
- {
- char namestore[256];
- char * filename = namestore;
- register rle_pixel *rptr, *gptr, *bptr, *aptr, *qdptr;
- register long i, j;
- PixMapPtr ppm;
- rle_pixel **rows;
- Rect r;
- QDErr err;
- DialogPtr progressDlog;
- char MMUMode = 1;
-
- r = mygw->portRect;
-
- inglob = rle_dflt_hdr; /* Initialize random stuff */
- inglob.xmin = r.left;
- inglob.xmax = r.right - 1;
- inglob.ymin = r.top;
- inglob.ymax = r.bottom - 1;
- inglob.ncolors = 3;
- inglob.alpha = 0; /* QD32 stomped on it! */
-
- if (defname)
- strcpy( filename, defname );
- else
- strcpy( filename, "RLE file" );
- if (! NewFilename( "RLE filename:", filename ) )
- return;
-
- CHECK( inglob.rle_file = fopen( filename, "wb" ), "Can't open output file" );
- progressDlog = InitProgress( 200 );
- rle_put_setup( &inglob );
- if ( rle_row_alloc( &inglob, &rows ) )
- MemoryError( "Can't allocate scanlines" );
-
- if ( !LockPixels( mygw->portPixMap ) )
- MemoryError( "Can't lock pixels in memory" );
-
- HLock( mygw->portPixMap );
-
- ppm = *(mygw->portPixMap);
-
- for (i = inglob.ymax; i >= inglob.ymin; i--)
- {
- rptr = &(rows[0][0]);
- gptr = &(rows[1][0]);
- bptr = &(rows[2][0]);
-
- qdptr = (rle_pixel *) &(ppm->baseAddr[(long) (i - (long) inglob.ymin)
- * (long) (ppm->rowBytes & 0x7FFF) + (long)0]);
-
- SwapMMUMode( &MMUMode ); /* ╔In case qdptr is off to a NuBus card */
-
- for (j = inglob.xmin; j <= inglob.xmax; j++)
- {
- qdptr++;
- *rptr++ = *qdptr++;
- *gptr++ = *qdptr++;
- *bptr++ = *qdptr++;
- }
-
- SwapMMUMode( &MMUMode );
-
- rle_putrow( rows, r.right - r.left, &inglob );
- if (i && (!(i % 10)))
- UpdateProgress( progressDlog,
- 1.0 - ((double) (i - inglob.ymin))
- / (double) (inglob.ymax - inglob.ymin));
- }
- HUnlock( mygw->portPixMap );
-
- UpdateProgress( progressDlog, 1.0 );
- fclose( inglob.rle_file );
- DoneProgress( progressDlog );
- }
-
- /*
- * The File menu drives the functionality of the
- * program.
- */
- void
- DoFileItem( short item )
- {
- char namestore[256];
- char * filename = namestore;
- GWorldPtr gw;
- ImageWin * imgWin;
- GWorldFlags flags = (1L << (long)clipPixBit) | (1L << (long)ditherPixBit);
-
- switch (item)
- {
- case 1: /* Open PICT */
- if (!OldFilename( "PICT file:", filename, 'PICT' ))
- return;
- gw = LoadPicture( filename );
- if (gw)
- CreateWindow( gw, filename );
- break;
-
- case 2: /* Save PICT */
- if (! (imgWin = (ImageWin *) GetWRefCon( FrontWindow() )))
- return;
-
- if (imgWin->tag != 0xDEADBEEF)
- return;
-
- if (imgWin->name)
- strcpy( filename, imgWin->name );
-
- if (!NewFilename( "Save PICT file as:", filename ))
- return;
-
- SavePicture( imgWin->gw, filename );
-
- break;
-
- case 4: /* Load RLE */
- RLEtoPICT();
- break;
-
- case 5: /* Save RLE */
- if (! (imgWin = (ImageWin *) GetWRefCon( FrontWindow() )))
- return;
-
- if (imgWin->tag != 0xDEADBEEF)
- return;
- /*
- * Force image to be 32 bits per pixel. Can only happen if we're
- * writing an RLE file we read, which is a pretty silly thing
- * to do anyway...
- */
- gw = imgWin->gw;
- if ( (*(gw->portPixMap))->pixelSize != 32 )
- flags = UpdateGWorld( &(imgWin->gw), 32, &gw->portRect, NULL, NULL, flags );
-
- if (flags & (1L << gwFlagErrBit))
- MemoryError( "Can't expand pixmap to 32 bits" );
-
- PICTtoRLE( imgWin->gw, imgWin->name );
- break;
-
- case 7:
- ExitToShell();
- break;
- }
- }
-
-
- main()
- {
- InitMac();
- PanicStash = NewPtr( 5000L ); /* Hopefully enough to bring up an error & exit */
- CreateMenus();
- EventLoop();
- }
-